﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using ZXing.Common;
using ZXing;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using CefSharp.WinForms;
using CefSharp;
using System.Security.Policy;
using CefSharp.DevTools.FedCm;

namespace QRReader200
{
    public partial class FrmMain : Form
    {
        private Thread thread;
        public FrmMain()
        {
            InitializeComponent();
        }
        ChromiumWebBrowser browser;
        private void Form1_Load(object sender, EventArgs e)
        {

            // 初始化 CEF  
            CefSettings settings = new CefSettings();
            // 可以在这里配置 CEF 的设置  
            Cef.Initialize(settings);

            // 创建并配置 CEF 浏览器控件  
            browser = new ChromiumWebBrowser("https://accounts.douban.com/passport/login");
            // 将浏览器控件添加到窗体的控件集合中  
            this.panelMain.Controls.Add(browser);
            browser.Dock = DockStyle.Fill;

            browser.FrameLoadEnd += Browser_FrameLoadEnd;

            new TextBoxDragDrop(txtImagePath);
            Control.CheckForIllegalCrossThreadCalls = false;
            this.FormClosing += (ss, ee) =>
            {
                Cef.Shutdown();
                if (thread != null && thread.IsAlive)
                    thread.Abort();
            };
        }

        private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
        {
            //string url = e.Url;
            //MyStringVisitor visitor = new MyStringVisitor(e.Url);
            //e.Frame.GetSource(visitor);

        }

        private async void parseHtml2UserInfo(DataRow dr)
        {
            UserInfo userInfo = new UserInfo();
            userInfo.FileName = Path.GetFileNameWithoutExtension((string)dr["fn"]);
            userInfo.Url = (string)dr["url"];
            if (!string.IsNullOrEmpty(userInfo.Url))
            {
                browser.Load(userInfo.Url);
                Thread.Sleep(5000);
                // 使用 EvaluateScriptAsync 方法执行 JavaScript 代码来获取 HTML 源码  

                var html = await browser.GetSourceAsync();

                userInfo.Name = getRegexValue(html, "<title>(?<value>[\\s\\S]+?)</title>");
                userInfo.IPLocation = getRegexValue(html, "<span class=\"ip-location\">IP属地：(?<value>.+?)</span>");
                userInfo.CreateTime = getRegexValue(html, "(?<value>\\d{4}-\\d{1,2}-\\d{1,2})加入 <br");
                string pattern = "<div class=\"pl\">([\\s\\S]+?)</div>";
                Regex regex = new Regex(pattern, RegexOptions.Compiled);
                MatchCollection mc = regex.Matches(html);
                foreach (Match match in mc)
                {
                    if (match.Value.Contains("加入") && match.Value.Contains("IP属地"))
                    {
                        Regex reg2 = new Regex("<div class=\"pl\">(?<nickname>[\\s\\S]+?)<br");
                        Match match2 = reg2.Match(html);
                        userInfo.NickName = match2.Groups["nickname"].Value.Trim();
                    }
                }
            }
            userInfos.Add(userInfo);
        }

        private static string getRegexValue(string input, string pattern)
        {
            Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
            Match match = regex.Match(input);
            return match.Groups["value"].Value.Trim();
        }

        private void btnExtract_Click(object sender, EventArgs e)
        {
            string imagePatg = txtImagePath.Text.Trim();
            if (!Directory.Exists(imagePatg))
            {
                MessageBox.Show("图片目录不存在", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "表格文件(*.xlsx)|*.xlsx";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                thread = new Thread(new ParameterizedThreadStart(workService));
                thread.Start(dlg.FileName);
            }
        }
        List<UserInfo> userInfos = new List<UserInfo>();

        private void workService(object obj)
        {
            try
            {
                userInfos.Clear();
                foreach (Control control in this.Controls) control.Enabled = false;
                this.Cursor = Cursors.WaitCursor;
                progressBar.Enabled = true;

                string savefn = (string)obj;
                string imagePatg = txtImagePath.Text.Trim();
                string[] files = Directory.GetFiles(imagePatg, "*.*", SearchOption.AllDirectories);
                DataTable dt = new DataTable();
                dt.Columns.Add("fn", typeof(string));
                dt.Columns.Add("num", typeof(int));
                dt.Columns.Add("id", typeof(string));
                dt.Columns.Add("url", typeof(string));
                List<string> extensions = new List<string>() { ".png", ".jpg", ".jpeg" };
                foreach (string file in files)
                {
                    string extension = Path.GetExtension(file).ToLower();
                    if (!extensions.Contains(extension)) continue;

                    string name = Path.GetFileNameWithoutExtension(file);
                    string str = Regex.Replace(name, "[^0-9]", "");
                    int num = -1;
                    int.TryParse(str, out num);
                    DataRow dr = dt.NewRow();
                    dr["fn"] = file;
                    dr["num"] = num;
                    dt.Rows.Add(dr);
                }
                DataView dv = new DataView(dt);
                dv.Sort = "num";
                DataTable dtNew = dv.ToTable();
                progressBar.Minimum = 0;
                progressBar.Maximum = dtNew.Rows.Count;
                progressBar.Value = 0;

                foreach (DataRow dr in dtNew.Rows)
                {
                    progressBar.Value += 1;
                    string filename = (string)dr["fn"];
                    dr["id"] = string.Empty;
                    dr["url"] = string.Empty;
                    // 加载图片  
                    using (var bitmap = new Bitmap(filename))
                    {
                        // 初始化二维码阅读器  
                        var reader = new BarcodeReader
                        {
                            AutoRotate = true,
                            TryInverted = true,
                            Options = new DecodingOptions
                            {
                                PureBarcode = false,
                                TryHarder = true,
                                PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE }
                            }
                        };
                        // 解码图片  
                        var result = reader.Decode(bitmap);
                        if (result != null)
                        {
                            string pattern = "people/(?<id>[0-9]+)/subject_profile";
                            Regex regex = new Regex(pattern, RegexOptions.Compiled);
                            Match match = regex.Match(result.ToString());
                            if (match.Success)
                            {
                                string id = match.Groups["id"].Value;
                                string url = $"https://www.douban.com/people/{id}/";
                                dr["id"] = id;
                                dr["url"] = url;
                            }
                            else
                            {
                                dr["url"] = result.ToString();
                            }
                        }
                    }
                }

                progressBar.Minimum = 0;
                progressBar.Maximum = dtNew.Rows.Count;
                progressBar.Value = 0;
                foreach (DataRow dr in dtNew.Rows)
                {
                    progressBar.Value += 1;
                    string url = (string)dr["url"];
                    if (!string.IsNullOrEmpty(url))
                    {
                        browser.Load(url);
                        Thread.Sleep(5000);
                        MyStringVisitor visitor = new MyStringVisitor(url);
                        browser.GetMainFrame().GetSource(visitor);
                        Thread.Sleep(3000);
                    }
                }

                DataTable dtExport = new DataTable();
                dtExport.Columns.Add("FileName", typeof(string));
                dtExport.Columns.Add("Name", typeof(string));
                dtExport.Columns.Add("Url", typeof(string));
                dtExport.Columns.Add("NickName", typeof(string));
                dtExport.Columns.Add("IPLocation", typeof(string));
                dtExport.Columns.Add("CreateTime", typeof(string));
                dtExport.Columns.Add("Visited", typeof(string));

                foreach (DataRow dr in dtNew.Rows)
                {
                    DataRow drEx = dtExport.NewRow();
                    string fn = (string)dr["fn"];
                    string url = (string)dr["url"];
                    string id = (string)dr["id"];

                    drEx["FileName"] = Path.GetFileNameWithoutExtension(fn);
                    drEx["Url"] = url;

                    string htmlfn = Path.Combine(Application.StartupPath, $"temp_htmls\\{id}.html");
                    if (File.Exists(htmlfn))
                    {
                        string html = File.ReadAllText(htmlfn, System.Text.Encoding.UTF8);
                        drEx["Name"] = getRegexValue(html, "<title>(?<value>[\\s\\S]+?)</title>");
                        drEx["IPLocation"] = getRegexValue(html, "<span class=\"ip-location\">IP属地：(?<value>.+?)</span>");
                        drEx["CreateTime"] = getRegexValue(html, "(?<value>\\d{4}-\\d{1,2}-\\d{1,2})加入 <br");
                        drEx["Visited"] = getRegexValue(html, ">(?<value>\\d+)部看过</a>");

                        string pattern = "<div class=\"pl\">([\\s\\S]+?)</div>";
                        Regex regex = new Regex(pattern, RegexOptions.Compiled);
                        MatchCollection mc = regex.Matches(html);
                        foreach (Match match in mc)
                        {
                            if (match.Value.Contains("加入") && match.Value.Contains("IP属地"))
                            {
                                Regex reg2 = new Regex("<div class=\"pl\">(?<nickname>[\\s\\S]+?)<br");
                                Match match2 = reg2.Match(html);
                                drEx["NickName"] = match2.Groups["nickname"].Value.Trim();
                            }
                        }
                    }
                    dtExport.Rows.Add(drEx);
                }
                DataTableToExcel(dtExport, savefn);
                MessageBox.Show("提取完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (ThreadAbortException) { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            finally
            {
                foreach (Control control in this.Controls) control.Enabled = true;
                this.Cursor = Cursors.Default;
            }
        }
        public static void DataTableToExcel(DataTable dt, string filePath)
        {
            // 创建一个Excel工作簿  
            IWorkbook workbook = new XSSFWorkbook();

            // 创建一个工作表sheet  
            ISheet sheet = workbook.CreateSheet("Sheet1");

            // 创建标题行  
            IRow row = sheet.CreateRow(0);

            foreach (DataColumn column in dt.Columns)
            {
                ICell cell = row.CreateCell(column.Ordinal);
                cell.SetCellValue(column.ColumnName);
            }

            // 填充数据  
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                row = sheet.CreateRow(i + 1);
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    ICell cell = row.CreateCell(j);
                    cell.SetCellValue(dt.Rows[i][j].ToString());
                }
            }

            // 写入文件  
            using (FileStream file = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                workbook.Write(file);
            }

        }
        private void btnImagePath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            string imagePath = txtImagePath.Text.Trim();
            if (Directory.Exists(imagePath))
            {
                dlg.SelectedPath = imagePath;
            }
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                txtImagePath.Text = dlg.SelectedPath;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            browser.Load("https://www.douban.com/people/78165455");
        }
    }
}
